﻿using Abp.Authorization.Users;
using Abp.Collections.Extensions;
using Abp.Dependency;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Extensions;
using Abp.Organizations;
using Abp.Runtime.Caching;
using Abp.Runtime.Session;
using Castle.Core.Internal;
using Castle.Core.Logging;
using Microsoft.EntityFrameworkCore;
using Mt.Organizations;
using Mt.Site.Core.Authorization.Users.Entities;
using Mt.Site.Core.Base.Authorization.Roles;
using Mt.Site.Core.Base.Authorization.Users;
using Mt.Site.Core.Common.Cache;
using Mt.Site.Core.Organizations.Posts;
using Mt.Site.Core.Organizations.UserCache.Models;
using Mt.Site.Core.WorkFlows.Common.Cache;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Core.Organizations.UserCache
{
    public class UserAndUnitFinder : IUserAndUnitFinder, ITransientDependency
    {
        private readonly IRepository<MtOrganizationUnit, long> _organizationUnitRepository;
        private readonly IRepository<UserOrganizationUnit, long> _userOrganizationUnitRepository;
        private readonly IRepository<Post, long> _postRepository;
        private readonly IRepository<UserPost, long> _userPostRepository;
        private readonly IRepository<PostOrganization, long> _postOrganizationRepository;
        private readonly IRepository<UserExtension, long> _userExtensionRepository;

        public RoleManager RoleManager { get; set; }
        public UserManager UserManager { get; set; }

        private readonly ICacheManager _cacheManager;
        public IAbpSession AbpSession { get; set; }

        public ILogger Loger { get; set; }

        public UserAndUnitFinder(
            ICacheManager cacheManager,
            IRepository<MtOrganizationUnit, long> organizationUnitRepository,
            IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
            IRepository<Post, long> postRepository,
            IRepository<UserPost, long> userPostRepository,
            IRepository<PostOrganization, long> postOrganizationRepository,
            IRepository<UserExtension, long> userExtensionRepository)
        {
            _cacheManager = cacheManager;
            _organizationUnitRepository = organizationUnitRepository;
            _userOrganizationUnitRepository = userOrganizationUnitRepository;
            _postRepository = postRepository;
            _userPostRepository = userPostRepository;
            _postOrganizationRepository = postOrganizationRepository;
            _userExtensionRepository = userExtensionRepository;

            AbpSession = NullAbpSession.Instance;
            Loger = NullLogger.Instance;
        }


        #region 用户检索

        /// <inheritdoc/>
        public async Task<List<long>> GetUserIdListByUnitId(long unitId)
        {
            var organizations = await GetAllUnitSelectionData();
            var currentUnit = organizations.Where(item => item.Id == unitId).FirstOrDefault();
            var unitIds = organizations.Where(item => item.Code.StartsWith(currentUnit.Code) || item.Code == currentUnit.Code).Select(item=>item.Id);

            var query = from user in UserManager.Users
                        join uru in _userOrganizationUnitRepository.GetAll().Where(item=>unitIds.Contains(item.OrganizationUnitId)) on user.Id equals uru.UserId
                        where user.IsActive 
                        select user.Id;

            return await query.Distinct().ToListAsync();
        }

        /// <inheritdoc/>
        public async Task<GetUserListResult> GetUserListAsync(
            List<long> limitedUnitIdList, List<long> limitedUserIdList, UserFilter userFilter, UserInfoDto autherInfo, long sponsoringUnitId)
        {
            List<UserSelectionData> list = await GetUserItemListAsync(limitedUnitIdList, limitedUserIdList);

            var defaultSelectedUsers = new List<UserSelectionData>();
            var allUsers = list;
            if (userFilter != null)
            {
                list = await FilterOperator(list, autherInfo, userFilter.BeforeSelectFilter, userFilter.BeforeSelectMoreFilter, sponsoringUnitId);
                if (userFilter.SelectedFilter != OperatorFilter.None || userFilter.SelectedMoreFilter.Length > 0)
                {
                    defaultSelectedUsers = await FilterOperator(list, autherInfo, userFilter.SelectedFilter, userFilter.SelectedMoreFilter, sponsoringUnitId);
                }
                else
                {
                    defaultSelectedUsers = new List<UserSelectionData>();
                }
            }
            foreach (var item in list)
            {
                var userInfo = await GetUserInfoAsync(item.Id);
                if (userInfo != null)
                {
                    item.NewPostLevel = userInfo.NewPostLevel;
                }
            }
            //补充上级部门
            var UserUnits = list.SelectMany(c => c.Units);
            List<UnitSelectionData> units = await GetUnitsWithTheirParents(UserUnits);

            var result = new GetUserSelectionDataOutput
            {
                Users = list.OrderByDescending(c => c.Order).ThenBy(c => c.Name).ToList(),
                Units = CheckUnits(units),
                DefaultSelectedUsers = defaultSelectedUsers.OrderByDescending(c => c.Order).ThenBy(c => c.Name).ToList()
            };

            return new GetUserListResult
            {
                Result =result,
                AllUsers = allUsers
            };
        }

        public async Task<List<string>> GetUserNameListAsync(List<long> idList)
        {
            var result = new List<string>();
            foreach (var item in idList)
            {
                var name = await GetUserNameAsync(item);
                result.Add(name);
            }
            return result;
        }

        public async Task<string> GetUserNameAsync(long id)
        {
            var cacheItem = await GetUserInfoAsync(id);
            return cacheItem?.UserName;
        }

        /// <inheritdoc/>
        public async Task<List<UnitSelectionData>> GetAllUnitSelectionData()
        {
            var list = await GetAllUnitCacheAsync();

            var units = list.Select(c => new UnitSelectionData
            {
                Id = c.Id,
                Name = c.Name,
                DisplayName = c.DisplayName,
                Code = c.Code,
                Level = c.Level,
                Order = c.Order,
                ParentId = c.ParentId
            }).ToList();

            var result = CheckUnits(units);
            return result;
        }

        private async Task<List<UserSelectionData>> FilterOperator(List<UserSelectionData> list, UserInfoDto autherInfo, OperatorFilter operatorFilter, string[] moreFilter, long sponsoringUnitId)
        {
            if ((operatorFilter != OperatorFilter.None && autherInfo != null) || moreFilter.Length > 0)
            {
                switch (operatorFilter)
                {
                    case OperatorFilter.Author:
                        var moreFilterUsers = await FindMoreFilterUsers(list, moreFilter);
                        moreFilterUsers.AddRange(list.Where(c => c.Id == autherInfo.UserId));
                        return moreFilterUsers.DistinctBy(c=>c.Id).ToList();
                    case OperatorFilter.SupervisorOfAutherUnits: //本部门负责人(主管或支持工作副职)
                        return await FindSupervisorOfTheDepartment(list, autherInfo, sponsoringUnitId, moreFilter);
                    case OperatorFilter.OfficeDirector:
                        return await FindOfficeDirector(list, autherInfo, sponsoringUnitId, moreFilter);
                    case OperatorFilter.ResponsibleLeader:
                        return await FindResponsibleLeader(list, autherInfo, sponsoringUnitId, moreFilter);
                    case OperatorFilter.MainLeaders:
                        return await FindMainLeaders(list, autherInfo, sponsoringUnitId, moreFilter);
                    case OperatorFilter.SelectAll:
                        return await SelectAll(list, autherInfo, sponsoringUnitId, moreFilter);
                }
            }

            return list;
        }

        #region 用户过滤

        private async Task<List<UserSelectionData>> FindMoreFilterUsers(
            List<UserSelectionData> list,
            string[] moreFilter)
        {
            var newlist = new List<UserSelectionData>();

            if (moreFilter.IsNullOrEmpty()) 
            {
                return newlist;
            }

            foreach (var user in list)
            {
                var userInfo = await GetUserInfoAsync(user.Id);
                foreach (var post in userInfo.Posts)
                {
                    if (moreFilter.Contains(post.UnqiueName))
                    {
                        newlist.Add(user);
                    }
                }
            }
            return newlist;
        }
        /// <summary>
        /// 部门负责人
        /// </summary>
        /// <param name="list"></param>
        /// <param name="autherInfo"></param>
        /// <returns></returns>
        private async Task<List<UserSelectionData>> FindSupervisorOfTheDepartment(
            List<UserSelectionData> list, UserInfoDto autherInfo, long sponsoringUnitId,
            string[] moreFilter)
        {
            long? unitId;
            if (sponsoringUnitId > 0)
            {
                //拟稿人的部门可能调整，所以直接用部门找
                unitId = sponsoringUnitId;
            }
            else
            {
                unitId = autherInfo.MainOrgnzation?.Id;
            }
            
            var newlist = new List<UserSelectionData>();

            foreach (var user in list)
            {
                var userInfo = await GetUserInfoAsync(user.Id);
                foreach (var post in userInfo.Posts)
                {
                    if (unitId == post.OrganizationId)
                    {
                         if(post.PostLevel == PostGroup.DepartmentHead
                            || post.PostLevel == PostGroup.OfficeDirector
                            || (post.PostLevel == PostGroup.DepartmentDeputyManager && post.DeputyPresiding)
                            ||  post.PostLevel == PostGroup.LeaderOfSubsidiary
                            || (post.PostLevel == PostGroup.DeputyLeaderOfSubsidiary && post.DeputyPresiding))
                        {
                            newlist.Add(user);
                        }
                    }

                    if (moreFilter.Contains(post.UnqiueName))
                    {
                        newlist.Add(user);
                    }
                }
            }
            return newlist.DistinctBy(c => c.Id).ToList();
        }

        /// <summary>
        /// 办公室主任(?)
        /// </summary>
        /// <param name="list"></param>
        /// <param name="autherInfo"></param>
        /// <returns></returns>
        private async Task<List<UserSelectionData>> FindOfficeDirector(List<UserSelectionData> list, UserInfoDto autherInfo, long sponsoringUnitId, string[] moreFilter)
        {
            var newlist = new List<UserSelectionData>();
            foreach (var user in list)
            {
                var userInfo = await GetUserInfoAsync(user.Id);
                foreach (var post in userInfo.Posts)
                {
                    if (post.PostLevel == PostGroup.OfficeDirector)
                    {
                        newlist.Add(user);
                        if(moreFilter.Length == 0)
                        {
                            return newlist;
                        }
                    }
                   
                    if (moreFilter.Contains(post.UnqiueName))
                    {
                        newlist.Add(user);
                    }
                }
            }
            return newlist.DistinctBy(c => c.Id).ToList();
        }

        /// <summary>
        /// 分管领导
        /// </summary>
        /// <param name="list"></param>
        /// <param name="autherInfo"></param>
        /// <returns></returns>
        private async Task<List<UserSelectionData>> FindResponsibleLeader(List<UserSelectionData> list, UserInfoDto autherInfo, long sponsoringUnitId, string[] moreFilter)
        {
            long? unitId;
            if (sponsoringUnitId > 0)
            {
                //拟稿人的部门可能调整，所以直接用部门找
                unitId = sponsoringUnitId;
            }
            else
            {
                unitId = autherInfo.MainOrgnzation?.Id;
            }

            var newlist = new List<UserSelectionData>();
            foreach (var user in list)
            {
                var userInfo = await GetUserInfoAsync(user.Id);
                foreach (var post in userInfo.Posts)
                {
                    if (post.PostLevel == PostGroup.ResponsibleLeader && post.PostOrganizations.Any(u => unitId == u))
                    {
                        newlist.Add(user);
                    }
                    
                    if (moreFilter.Contains(post.UnqiueName))
                    {
                        newlist.Add(user);
                    }
                }
            }
            return newlist.DistinctBy(c => c.Id).ToList();
        }

        /// <summary>
        /// 主要领导（总经理或董事长）
        /// </summary>
        /// <param name="list"></param>
        /// <param name="autherInfo"></param>
        /// <returns></returns>
        private async Task<List<UserSelectionData>> FindMainLeaders(List<UserSelectionData> list, UserInfoDto autherInfo, long sponsoringUnitId, string[] moreFilter)
        {
            var newlist = new List<UserSelectionData>();
            foreach (var user in list)
            {
                var userInfo = await GetUserInfoAsync(user.Id);
                foreach (var post in userInfo.Posts)
                {
                    if (post.PostLevel == PostGroup.GeneralManager || post.PostLevel == PostGroup.Chairman)
                    {
                        newlist.Add(user);
                    }
                    
                    if (moreFilter.Contains(post.UnqiueName))
                    {
                        newlist.Add(user);
                    }
                }
            }
            return newlist.DistinctBy(c => c.Id).ToList();
        }

        /// <summary>
        /// 选取被选项里的全部
        /// </summary>
        /// <param name="list"></param>
        /// <param name="autherInfo"></param>
        /// <param name="sponsoringUnitId"></param>
        /// <param name="moreFilter"></param>
        /// <returns></returns>
        private async Task<List<UserSelectionData>> SelectAll(List<UserSelectionData> list, UserInfoDto autherInfo, long sponsoringUnitId, string[] moreFilter)
        {
            await Task.FromResult(0);
            return list.DistinctBy(c => c.Id).ToList();
        }

        #endregion


        /// <inheritdoc/>
        public async Task<List<UnitSelectionData>> GetUnitsWithTheirParents(List<long> UserIdList)
        {
            var cache = await GetAllUserCacheAsync();

            var list = new List<UnitSelectionData>();

            foreach (var item in cache)
            {
                if (UserIdList == null || UserIdList.Count == 0 || UserIdList.Contains(item.Id))
                {
                    list.AddRange(item.Units.Select(c => new UnitSelectionData
                    {
                        Id = c.Id,
                        Name = c.Name,
                        DisplayName = c.DisplayName,
                        Code = c.Code,
                        ParentId = c.ParentId
                    }));
                }
            }

            var data = await GetUnitsWithTheirParents(list);
            return CheckUnits(data);
        }

        //jstree
        /// <inheritdoc/>
        public async Task<List<UnitSelectionData>> GetUnitsWithTheirParents(IEnumerable<UnitSelectionData> unitUnits)
        {
            var distinctCodes = unitUnits.Select(u => u.Code).Distinct().ToList();

            var missingCodes = new List<string>();
            foreach (var code in distinctCodes)
            {
                var temp = code.Split('.');
                var tempStr = "";
                for (int i = 0; i < temp.Length - 1; i++)
                {
                    var item = temp[i];
                    tempStr += item;
                    if (!missingCodes.Contains(tempStr) && !distinctCodes.Contains(tempStr))
                    {
                        missingCodes.Add(tempStr);
                    }
                    tempStr += ".";
                }
            }

            var unitCache = await GetAllUnitCacheAsync();
            var units = unitCache.Where(unit => missingCodes.Contains(unit.Code) || distinctCodes.Contains(unit.Code))
                .Select(c => new UnitSelectionData
                {
                    Id = c.Id,
                    Name = c.Name,
                    DisplayName = c.DisplayName,
                    Code = c.Code,
                    ParentId = c.ParentId,
                    Level = c.Level,
                    Order = c.Order
                }).ToList();

            return units;
        }

        /// <summary>
        /// 排序（为选择框准备数据源）
        /// </summary>
        /// <param name="scoure"></param>
        /// <returns></returns>
        private List<UnitSelectionData> CheckUnits(List<UnitSelectionData> scoure)
        {
            scoure = scoure.OrderBy(c => c.Code).ToList();
            var result = new List<UnitSelectionData>();
            var lv1 = scoure.Where(c => c.Level == 1);
            foreach (var item in lv1)
            {
                result.Add(item);
                AddSubUnit(item.Code, scoure, result, item.Level + 1);
            }
            return result;
        }

        private void AddSubUnit(string parentCode, List<UnitSelectionData> scoure, List<UnitSelectionData> result, int level)
        {
            var list = scoure.Where(c => c.Code.StartsWith(parentCode) && c.Level == level);
            foreach (var item in list)
            {
                result.Add(item);
                AddSubUnit(item.Code, scoure, result, item.Level + 1);
            }
        }

        #endregion

        #region 用户缓存
        public async Task<UserInfoDto> GetUserInfoAsync(int? tenantId, long userId) 
        {
            var cacheKey = $"{userId}@{tenantId ?? 0}";
            var item = await _cacheManager.GetUserInfoCache().GetAsync(cacheKey, async () => await GetUserInfoCacheItemAsync(userId));
            if (item != null)
            {
                var result = new UserInfoDto
                {
                    UserId = item.UserId,
                    Order = item.Order,
                    LoginName =item.LoginName,
                    UserName = item.UserName,
                    TenantId = item.TenantId,
                    Surname = item.Surname,
                    PhoneNumber = item.PhoneNumber
                };

                result.Units = new List<UnitSelectionData>(item.Units);

                result.Posts = new List<PostItemData>(item.Posts);

                result.MainOrgnzation = item.MainOrgnzation;

                result.NewPostLevel = item.NewPostLevel;

                return result;
            }
            return null;
        }

        public async Task<UserInfoDto> GetUserInfoAsync(long userId)
        {
            return await GetUserInfoAsync(AbpSession.TenantId, userId);
        }

        public UserInfoDto GetUserInfo(int? tenantId, long userId)
        {
            var cacheKey = $"{userId}@{tenantId ?? 0}";
            var item = _cacheManager.GetUserInfoCache().Get(cacheKey, () => GetUserInfoCacheItem(userId));
            if (item != null)
            {
                var result = new UserInfoDto
                {
                    UserId = item.UserId,
                    Order = item.Order,
                    LoginName = item.LoginName,
                    UserName = item.UserName,
                    TenantId = item.TenantId,
                    Surname = item.Surname,
                    PhoneNumber = item.PhoneNumber
                };

                result.Units = new List<UnitSelectionData>(item.Units);

                result.Posts = new List<PostItemData>(item.Posts);

                result.MainOrgnzation = item.MainOrgnzation;

                result.NewPostLevel = item.NewPostLevel;

                return result;
            }
            return null;
        }
        public UserInfoDto GetUserInfo(long userId)
        {
            return GetUserInfo(AbpSession.TenantId, userId);
        }

        public async Task<UserInfoDto> GetCurrentUserInfoAsync()
        {
            var userId = AbpSession.UserId;
            if (userId.HasValue)
            {
                return await GetUserInfoAsync(userId.Value);
            }
            return null;
        }

        public UserInfoDto GetCurrentUserInfo()
        {
            var userId = AbpSession.UserId;
            if (userId.HasValue)
            {
                return GetUserInfo(userId.Value);
            }
            return null;
        }

        [UnitOfWork]
        private async Task<UserInfoCacheItem> GetUserInfoCacheItemAsync(long userId)
        {
            var cache = await GetAllUserCacheAsync();

            foreach (var item in cache)
            {
                if (item.Id == userId)
                {
                    var cacheItem = new UserInfoCacheItem();
                    cacheItem.UserId = item.Id;
                    cacheItem.LoginName = item.UserName;
                    cacheItem.UserName = item.Name;
                    cacheItem.TenantId = item.TenantId;
                    cacheItem.Order = item.Order;
                    cacheItem.Surname = item.Surname;
                    cacheItem.PhoneNumber = item.PhoneNumber;

                    cacheItem.Units = item.Units.Select(unit => new UnitSelectionData
                    {
                        Id = unit.Id,
                        Name = unit.Name,
                        DisplayName = unit.DisplayName,
                        Code = unit.Code,
                        ParentId = unit.ParentId,
                        Level = unit.Level,
                        Order = unit.Order
                    }).OrderBy(c => c.Code).ToList();

                    cacheItem.Posts = item.Posts.Select(post => new PostItemData
                    {
                        Id = post.Id,
                        ShortName = post.ShortName,
                        DisplayName = post.DisplayName,
                        Order = post.Order,
                        OrganizationId = post.OrganizationId,
                        UnqiueName = post.UnqiueName,
                        PostLevel = post.PostLevel,
                        DeputyPresiding = post.DeputyPresiding,
                        PostOrganizations = post.PostOrganizations
                    }).OrderByDescending(c => c.PostLevel).ToList();

                    var userExtension = await _userExtensionRepository.FirstOrDefaultAsync(c => c.UserId == cacheItem.UserId);
                    if (userExtension == null || userExtension.MainUnitId <= 0)
                    {
                        cacheItem.MainOrgnzation = cacheItem.Units.FirstOrDefault();
                    }
                    else
                    {
                        cacheItem.MainOrgnzation = cacheItem.Units.FirstOrDefault(c => c.Id == userExtension.MainUnitId);
                    }
                    //if (cacheItem.MainOrgnzation == null)
                    //{
                    //    Loger.Error($"用户：{cacheItem.UserName},{cacheItem.UserId} 没有部门");
                    //}
                    cacheItem.NewPostLevel = Transform(cacheItem.Posts, cacheItem.MainOrgnzation?.Id);

                    return cacheItem;
                }
            }

            return null;
        }

        [UnitOfWork]
        private UserInfoCacheItem GetUserInfoCacheItem(long userId)
        {
            var cache = GetAllUserCache();

            foreach (var item in cache)
            {
                if(item.Id == userId)
                {
                    var cacheItem = new UserInfoCacheItem();
                    cacheItem.UserId = item.Id;
                    cacheItem.LoginName = item.UserName;
                    cacheItem.UserName = item.Name;
                    cacheItem.TenantId = item.TenantId;
                    cacheItem.Order = item.Order;
                    cacheItem.Surname = item.Surname;
                    cacheItem.PhoneNumber = item.PhoneNumber;

                    cacheItem.Units = item.Units.Select(unit => new UnitSelectionData 
                    {
                        Id = unit.Id,
                        Name = unit.Name,
                        DisplayName = unit.DisplayName,
                        Code = unit.Code,
                        ParentId = unit.ParentId,
                        Level = unit.Level,
                        Order = unit.Order
                    }).OrderBy(c => c.Code).ToList();

                    cacheItem.Posts = item.Posts.Select(post => new PostItemData
                    {
                        Id = post.Id,
                        ShortName = post.ShortName,
                        DisplayName = post.DisplayName,
                        Order = post.Order,
                        OrganizationId = post.OrganizationId,
                        UnqiueName = post.UnqiueName,
                        PostLevel = post.PostLevel,
                        DeputyPresiding = post.DeputyPresiding,
                        PostOrganizations = post.PostOrganizations
                    }).OrderByDescending(c => c.PostLevel).ToList();

                    var userExtension = _userExtensionRepository.FirstOrDefault(c => c.UserId == cacheItem.UserId);
                    if (userExtension == null || userExtension.MainUnitId <= 0)
                    {
                        cacheItem.MainOrgnzation = cacheItem.Units.FirstOrDefault();
                    }
                    else
                    {
                        cacheItem.MainOrgnzation = cacheItem.Units.FirstOrDefault(c => c.Id == userExtension.MainUnitId);
                    }
                    //if (cacheItem.MainOrgnzation == null)
                    //{
                    //    Loger.Error($"用户：{cacheItem.UserName},{cacheItem.UserId} 没有部门");
                    //}
                    cacheItem.NewPostLevel = Transform(cacheItem.Posts, cacheItem.MainOrgnzation?.Id);

                    return cacheItem;
                }
            }

            return null;
        }


        private NewPostLevel Transform(IReadOnlyList<PostItemData> posts, long? mainUnitId)
        {
            PostItemData mainPost = null;
            foreach (var post in posts)
            {
                if(mainUnitId == post.OrganizationId)
                {
                    mainPost = post;
                    break;
                }
            }

            if(mainPost == null)
            {
                return NewPostLevel.Member;
            }

            if (mainPost.PostLevel == PostGroup.Chairman)
            {
                return NewPostLevel.Chairman;
            }

            if (mainPost.PostLevel == PostGroup.GeneralManager)
            {
                return NewPostLevel.GeneralManager;
            }

            if (mainPost.PostLevel == PostGroup.ResponsibleLeader)
            {
                return NewPostLevel.ResponsibleLeader;
            }

            if (mainPost.PostLevel == PostGroup.DepartmentHead
            || mainPost.PostLevel == PostGroup.OfficeDirector
            || mainPost.PostLevel == PostGroup.LeaderOfSubsidiary)
            {
                return NewPostLevel.MidManager;
            }

            if ((mainPost.PostLevel == PostGroup.DepartmentDeputyManager || mainPost.PostLevel == PostGroup.DeputyLeaderOfSubsidiary)
            && mainPost.DeputyPresiding)
            {
                return NewPostLevel.MidDeputyManagerPresiding;
            }

            if ((mainPost.PostLevel == PostGroup.DepartmentDeputyManager || mainPost.PostLevel == PostGroup.DeputyLeaderOfSubsidiary)
            && !mainPost.DeputyPresiding)
            {
                return NewPostLevel.MidDeputyManager;
            }

            if(mainPost.PostLevel == PostGroup.OfficeDirectorOfSubsidiary)
            {
                return NewPostLevel.OfficeDirectorOfSubsidiary;
            }

            return NewPostLevel.Member;
        }

        #endregion


        #region 用户集合缓存

        public async Task<List<UserSelectionData>> GetUserItemListAsync(List<long> limitedUnitIdList, List<long> limitedUserIdList)
        {
            var cache = await GetAllUserCacheAsync();

            var result = new List<UserSelectionData>();

            foreach (var item in cache)
            {
                if(limitedUserIdList == null || limitedUserIdList.Count == 0 || limitedUserIdList.Contains(item.Id))
                {
                    if (limitedUnitIdList == null || limitedUnitIdList.Count == 0)
                    {
                        result.Add(new UserSelectionData
                        {
                            Name = item.Name,
                            Surname = item.Surname,
                            Id = item.Id,
                            Order = item.Order,
                            Units = item.Units.Select(u => new UnitSelectionData
                            {
                                Id = u.Id,
                                Name = u.Name,
                                DisplayName = u.DisplayName,
                                Code = u.Code,
                                ParentId = u.ParentId,
                                Level = u.Level
                            }).ToList()
                        });
                    }
                    else
                    {
                        var units = item.Units.Where(c => limitedUnitIdList.Contains(c.Id)).ToList();
                        if(units.Count > 0)
                        {
                            result.Add(new UserSelectionData
                            {
                                Name = item.Name,
                                Surname = item.Surname,
                                Id = item.Id,
                                Order = item.Order,
                                Units = units.Select(u => new UnitSelectionData
                                {
                                    Id = u.Id,
                                    Name = u.Name,
                                    DisplayName = u.DisplayName,
                                    Code = u.Code,
                                    ParentId = u.ParentId,
                                    Level = u.Level
                                }).ToList()
                            });
                        }
                    }
                }
            }

            return result;
        }


        [UnitOfWork]
        public async Task<List<UserListCacheItem>> GetAllUserCacheAsync()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);
            var list = await _cacheManager.GetAllUsersCache().GetAsync(cacheKey, async () => {

                var userPostData = await _userPostRepository.GetAllListAsync();
                var userUnitData = await _userOrganizationUnitRepository.GetAllListAsync();

                var postCache = await GetAllPostCacheAsync();
                var unitCache = await GetAllUnitCacheAsync();

                var query = from user in UserManager.Users
                            where user.IsActive
                            select new UserListCacheItem
                            {
                                Id = user.Id,
                                Name = user.Name,
                                UserName = user.UserName,
                                Surname = user.Surname,
                                Order = user.Order,
                                PhoneNumber = user.PhoneNumber,
                                TenantId = user.TenantId
                            };

                var result = await query.ToListAsync();

                foreach (var item in result)
                {
                    item.Units = userUnitData
                    .Where(c => c.UserId == item.Id)
                    .Select(c => unitCache.FirstOrDefault(u => u.Id == c.OrganizationUnitId))
                    .Where(c => c != null)
                    .ToList();

                    item.Posts = userPostData
                    .Where(c => c.UserId == item.Id)
                    .Select(c => postCache.FirstOrDefault(u => u.Id == c.PostId))
                    .Where(c => c != null)
                    .ToList();
                }

                return result;
            });

            return list;
        }

        [UnitOfWork]
        public List<UserListCacheItem> GetAllUserCache()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);

            var list = _cacheManager.GetAllUsersCache().Get(cacheKey, () => {

                var userPostData = _userPostRepository.GetAllList();
                var userUnitData = _userOrganizationUnitRepository.GetAllList();

                var postCache = GetAllPostCache();
                var unitCache = GetAllUnitCache();

                var query = from user in UserManager.Users
                            where user.IsActive
                            select new UserListCacheItem
                            {
                                Id = user.Id,
                                Name = user.Name,
                                UserName = user.UserName,
                                Surname = user.Surname,
                                Order = user.Order,
                                PhoneNumber = user.PhoneNumber,
                                TenantId = user.TenantId
                            };

                var result = query.ToList();

                foreach (var item in result)
                {
                    item.Units = userUnitData
                    .Where(c => c.UserId == item.Id)
                    .Select(c => unitCache.FirstOrDefault(u => u.Id == c.OrganizationUnitId))
                    .Where(c => c != null)
                    .ToList();

                    item.Posts = userPostData
                    .Where(c => c.UserId == item.Id)
                    .Select(c => postCache.FirstOrDefault(u => u.Id == c.PostId))
                    .Where(c => c != null)
                    .ToList();
                }

                return result;
            });

            return list;
        }

        [UnitOfWork]
        public async Task<List<UserOrganinzedCacheItem>> GetUserOrganinzedCacheAsync()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);

            var result = await _cacheManager.GetAllUserOrganinzedCache().GetAsync(cacheKey, async () => {

                var query = from user in UserManager.Users.Where(item => item.IsActive)
                            join userOrganizat in _userOrganizationUnitRepository.GetAll()
                            on user.Id equals userOrganizat.UserId
                            select new UserOrganinzedCacheItem
                            {
                                Id = user.Id,
                                DisplayName = user.Name,
                                Surname = user.Surname,
                                Order = user.Order,
                                OrganizationId = userOrganizat.OrganizationUnitId
                            };
                query = query.OrderByDescending(item => item.Order)
                             .ThenBy(item => item.DisplayName);

                var list = await query.ToListAsync();
                var userList2 = new List<long>();
                foreach (var item in list)
                {
                    var userInfo = await GetUserInfoAsync(item.Id);
                    if (userInfo != null)
                    {
                        if (userInfo.MainOrgnzation != null)
                        {
                            item.NewPostLevel = userInfo.NewPostLevel;
                            item.Posts = userInfo.Posts.Where(c => c.OrganizationId == item.OrganizationId).ToList();
                            item.MainOrganizationId = userInfo.MainOrgnzation.Id;
                        }
                        else
                        {
                            userList2.Add(item.Id);
                            //Logger.Debug($"用户id:{item.Id}({item.DisplayName},{item.Surname}), 未找到缓存数据({userInfo == null})或 主部门为空{userInfo.MainOrgnzation == null}");
                        }
                    }
                }

                //if (userList2.Count > 0)
                //{
                //    //用户的所有部门都已移除或撤销发布（若要恢复，先恢复部门，再到部门管理里查找用户，批量恢复）
                //    foreach (var item in userList2.Distinct())
                //    {
                //        await UserManager.SetNotActiveAsync(item);
                //    }
                //}

                return list;
            });

            return result;
        }

        #endregion



        #region 部门缓存


        [UnitOfWork]
        public async Task<List<UnitSelectionData>> GetAllUnitCacheAsync()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);
            var list = await _cacheManager.GetAllUnitsCache().GetAsync(cacheKey, async () => {

                var query = from unit in _organizationUnitRepository.GetAll()
                    .Where(item => item.IsActive)
                            select new UnitSelectionData
                            {
                                Id = unit.Id,
                                Name = unit.ShortName,
                                DisplayName = unit.DisplayName,
                                Code = unit.Code,
                                ParentId = unit.ParentId 
                            };
                var units = await query.ToListAsync();
                units.ForEach(c =>
                {
                    c.Level = c.Code.Split('.').Length;
                    c.Order = Convert.ToInt32(OrganizationUnit.GetLastUnitCode(c.Code));
                });

                return units;
            });

            return list;
        }

        [UnitOfWork]
        public List<UnitSelectionData> GetAllUnitCache()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);

            var list = _cacheManager.GetAllUnitsCache().Get(cacheKey, () => {

                var query = from unit in _organizationUnitRepository.GetAll()
                    .Where(item => item.IsActive)
                            select new UnitSelectionData
                            {
                                Id = unit.Id,
                                Name = unit.ShortName,
                                DisplayName = unit.DisplayName,
                                Code = unit.Code,
                                ParentId = unit.ParentId
                            };
                var units = query.ToList();
                units.ForEach(c =>
                {
                    c.Level = c.Code.Split('.').Length;
                    c.Order = Convert.ToInt32(OrganizationUnit.GetLastUnitCode(c.Code));
                });

                return units;
            });

            return list;
        }

        #endregion

        #region 职务缓存


        [UnitOfWork]
        public async Task<List<PostItemData>> GetAllPostCacheAsync()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);
            var list = await _cacheManager.GetAllPostsCache().GetAsync(cacheKey,async () => {

                var postOrganizationData = await _postOrganizationRepository.GetAllListAsync();

                var query = from post in _postRepository.GetAll()
                            join un in _organizationUnitRepository.GetAll() on post.OrganizationId equals un.Id
                            where post.IsActive && un.IsActive
                            select new PostItemData
                            {
                                Id = post.Id,
                                ShortName = post.ShortName,
                                DisplayName = post.DisplayName,
                                Order = post.Order,
                                OrganizationId = post.OrganizationId,
                                UnqiueName = post.UnqiueName,
                                PostLevel = post.PostLevel,
                                DeputyPresiding = post.DeputyPresiding
                            };


                var result = await query.ToListAsync();

                result = result.DistinctBy(c => c.Id).ToList();
                foreach (var item in result)
                {
                    if (item.PostLevel == PostGroup.ResponsibleLeader)
                    {
                        item.PostOrganizations = postOrganizationData.Where(c => c.PostId == item.Id).Select(c => c.OrganizationId).ToList();
                    }
                }

                return result;
            });

            return list;
        }

        [UnitOfWork]
        public List<PostItemData> GetAllPostCache()
        {
            var cacheKey = _cacheManager.GetCommonCacheKey(AbpSession.TenantId);

            var list = _cacheManager.GetAllPostsCache().Get(cacheKey, () => {

                var postOrganizationData = _postOrganizationRepository.GetAllList();

                var query = from post in _postRepository.GetAll()
                            join un in _organizationUnitRepository.GetAll() on post.OrganizationId equals un.Id
                            where post.IsActive && un.IsActive
                            select new PostItemData
                            {
                                Id = post.Id,
                                ShortName = post.ShortName,
                                DisplayName = post.DisplayName,
                                Order = post.Order,
                                OrganizationId = post.OrganizationId,
                                UnqiueName = post.UnqiueName,
                                PostLevel = post.PostLevel,
                                DeputyPresiding = post.DeputyPresiding
                            };

                var result = query.ToList();

                result = result.DistinctBy(c => c.Id).ToList();
                foreach (var item in result)
                {
                    if (item.PostLevel == PostGroup.ResponsibleLeader)
                    {
                        item.PostOrganizations = postOrganizationData.Where(c => c.PostId == item.Id).Select(c => c.OrganizationId).ToList();
                    }
                }

                return result;
            });

            return list;
        }


        #endregion

        /// <inheritdoc/>
        public async Task<List<PostItemData>> GetAllPostAsync()
        {
            var list = await GetAllPostCacheAsync();

            return list
                .Select(c => new PostItemData {
                    Id = c.Id,
                    ShortName = c.ShortName,
                    DisplayName = c.DisplayName,
                    Order = c.Order,
                    OrganizationId = c.OrganizationId,
                    UnqiueName = c.UnqiueName,
                    PostLevel = c.PostLevel,
                    DeputyPresiding = c.DeputyPresiding
                })
                .ToList();
        }

        /// <inheritdoc/>
        public async Task<SpecialUserData> GetSpecialUserDataAsync()
        {
            var outUsers = await GetUserItemListAsync(null, null);
            
            var specialUserData = new SpecialUserData();
            foreach (var item in outUsers)
            {
                var userInfo = GetUserInfo(item.Id);
                if (UserAndUnitFinderHelper.IsChairman(userInfo))
                {
                    specialUserData.Chairman = userInfo;
                }

                if (UserAndUnitFinderHelper.IsGeneralManager(userInfo))
                {
                    specialUserData.GeneralManager = userInfo;
                }

                if (UserAndUnitFinderHelper.IsOfficeDirector(userInfo))
                {
                    specialUserData.OfficeDirector = userInfo;
                }
            }
            return specialUserData;
        }
    }
}
